<?php
use Phalcon\Mvc\Controller;
use Phalcon\Db\Column;
use Phalcon\Http\Response;

class ApiController extends Controller {

    private $SIGNIN_SUCCESS;
    private $SIGNIN_FAILED;
    private $DATA_ILLEGEAL;
    private $HAD_SIGNIN;

    private $result;
    private $list_per_page;
    private $the_date;
    private $sql_handle;

    public function initialize() {
        //init respone data
        $this->result = array(
            'code'  =>  "",
            'message'   =>  "",
            'count' =>  0,
            'data'  =>  array()
        );

        //init list size
        $this->list_per_page = 10;

        //init the date
        $this->the_date = date('Y-m-d H:i:s');

        //init sql handle
        $this->sql_handle = (new SqlController())->setClassName("ApiController");

        //init respone status
        $this->ACTION_SUCCESS = $this->setStatusCode(900, '操作成功');
        $this->SIGNIN_SUCCESS = $this->setStatusCode(910, '登陆成功');
        $this->HAD_SIGNIN     = $this->setStatusCode(911, '已经登陆');
        $this->NOT_SIGNIN     = $this->setStatusCode(912, '尚未登陆');
        $this->SIGNIN_FAILED = $this->setStatusCode(810, '用户名或密码错误');
        $this->USERNAME_HAVE_BEEN_USED = $this->setStatusCode(811, '该用户名已经被占用');
        $this->ACTION_FAILED = $this->setStatusCode(800, '操作失败');
        $this->DATA_ILLEGEAL = $this->setStatusCode(801, '非法输入');
        $this->PLEASE_SIGNIN = $this->setStatusCode(802, '请登陆');
        $this->NO_DATA       = $this->setStatusCode(803, '无相关数据');
        $this->CANNOT_BE_NULL= $this->setStatusCode(820, '内容不能为空');
        $this->NO_TEXT       = $this->setStatusCode(821, '没有该文章');
        $this->NO_BLOG       = $this->setStatusCode(822, '没有该博客');
        $this->NO_LINK       = $this->setStatusCode(823, '没有该链接');
        $this->NO_USER       = $this->setStatusCode(824, '没有该用户');
        $this->NO_COMMENT    = $this->setStatusCode(825, '没有该评论');
        $this->NO_WORD       = $this->setStatusCode(826, '没有该留言');
        $this->URL_WRONG     = $this->setStatusCode(831, '链接格式错误');
    }

    private function echoResult($status, $data = array(), $isList = false) {
        if(!$isList) {
            //has data ?
            if(count($data) != 0) {
                $data = array($data);
            }
        }

        $this->result['code'] = $status['code'];
        $this->result['message'] = $status['message'];
        $this->result['count'] = count($data);
        $this->result['data'] = $data;

        //Cross Domain, http header
        $response = new Response();
        $response->setHeader("Access-Control-Allow-Credentials", "true");
        $response->setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
        $response->send();

        echo json_encode($this->result, JSON_UNESCAPED_UNICODE);
    }

    private function checkURL($url) {
        return preg_match("/^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\’:+!]*([^<>\”])*$/", $url);
    }

    private function handleNullInput($string) {
        if($string == "NULL") {
            return "";
        }else {
            return $string;
        }
    }

    public function indexAction($name = "test") {
        $this->session->set("user-name", $name);
    }

    public function showAction() {
        if ($this->session->has("lb-user")) {
            $user = $this->session->get("lb-user");
            echo $user->getUsername();
        }
    }

    /*
     * @param useranme and password
     * @print json(result)
    */
    public function signInAction($username, $password) {
        //check sql injection
        $this->sql_handle->checkString($username);

        if($this->session->has("lb-user")) {
            $user = $this->session->get("lb-user");

            if($user->getUsername() == $username) {
                $this->echoResult($this->HAD_SIGNIN, $user->convertToArray());
                return;
            }
        }

        $password = sha1($password);

        $parameters = array(
            "username" => $username,
            "password" => $password
        );

        $types = array(
            "username" => Column::BIND_PARAM_STR,
            "password" => Column::BIND_PARAM_STR
        );

        $user = Users::findFirst(array(
            "username = :username: AND password = :password:",
            "bind"      =>  $parameters,
            "bindTypes" =>  $types
        ));

        if($user) {

            //update login date, not neet to check the save()
            $blog = $user->blogs;
            $blog->setLoginDate($this->the_date);
            $blog->save();
            //echo $user->roles->getRoleIds();
            $this->echoResult($this->SIGNIN_SUCCESS, $user->convertToArray());
            $this->session->set('lb-user', $user);
            //TODO: 处理登陆后的状态
        }else {
            $this->echoResult($this->SIGNIN_FAILED);
        }


    }

    /*
     * @param useranme and password
     * @print json(result)
    */
    public function injectableAction($username, $password) {
        //check sql injection
        $this->sql_handle->checkString($username);

        $password = sha1($password);
        $user = Users::findFirst("username = '$username'");

        if($user) {
            $this->echoResult($this->SIGNIN_SUCCESS, $user->convertToArray());
        }else {
            $this->echoResult($this->SIGNIN_FAILED);
        }
    }

    private function setStatusCode($code, $message) {
        return array(
            'code'  =>  $code,
            'message'   =>  $message
        );
    }

    /*
     * @param useranme, password, blogType(int)
     * @print json()
    */
    public function signUpAction($username, $password, $blogType) {
        //check sql injection
        //password has to be hash, no need to check
        $this->sql_handle->checkString($username);
        $this->sql_handle->checkInt($blogType);

        //check whether had signup
        $require = "username = :username:";

        $parameters = array(
            "username" => $username
        );

        $types = array(
            "username" => Column::BIND_PARAM_STR
        );

        $user = Users::findFirst(array(
            $require,
            "bind"      =>  $parameters,
            "bindTypes" =>  $types
        ));

        if($user) {
            $this->echoResult($this->USERNAME_HAVE_BEEN_USED);
            return;
        }

        $user = new Users();
        $user->setUsername($username);
        $user->setPassword($password);
        $user->setRole(1);  //set as normal user



        if($user->save() == false) {
            $this->echoResult($this->ACTION_FAILED);
        }else {

            $blog = new Blogs();
            $blog->setUser($user->getId());
            $blog->setBlogType($blogType);
            $blog->setCreateDate($this->the_date);
            $blog->setLoginDate($this->the_date);

            if($blog->save() == false) {
                $user->delete();
                $this->echoResult($this->ACTION_FAILED);
            }else {
                $this->echoResult($this->ACTION_SUCCESS);
            }
        }
    }

    /*
     * @param none
     * @print json(result)
    */
    public function getCurrentUserAction() {
        if($this->session->has("lb-user")) {
            $user = $this->session->get("lb-user");
            $this->echoResult($this->ACTION_SUCCESS, $user->convertToArray());
        }else {
            $this->echoResult($this->NOT_SIGNIN);
        }
    }

    /*
     * @param none, require post data
     * @print json()
    */
    public function createNewTextAction() {
        if ($this->session->has("lb-user")) {
            $user = $this->session->get("lb-user");

            $request = $this->request;
            if ($request->isPost() == true) {

                $title = $request->getPost("title");
                $text_type = $request->getPost("text_type");
                $textData = $request->getPost("text");
                $create_date = $this->the_date;
                $update_date = $this->the_date;

                //check sql injection
                //no need to stop the program
                $this->sql_handle->checkString($title);
                $this->sql_handle->checkString($textData);
                $this->sql_handle->checkInt($text_type);

                $text = new Texts();
                $text->setAuthor($user->getId());
                $text->setTitle($title);
                $text->setTextType($text_type);
                $text->setText($textData);
                $text->setVisible(1);
                $text->setRecommend(0);
                $text->setStatus(0);
                $text->setCreateDate($create_date);
                $text->setUpdateDate($update_date);

                if($text->save()) {
                    $this->echoResult($this->ACTION_SUCCESS, $text->convertToArray());
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->PLEASE_SIGNIN);
        }
    }

    /*
     * @param nothing
     * @print json()
     */
    public function logoutAction() {
        $this->session->remove("lb-user");

        $this->echoResult($this->ACTION_SUCCESS);
    }

    /*
     * @param page_num, text_type(like), author(like), title(like), text(like), create_date(like)
     * order by update_date, limit by list_per_page
     * @print json(result) and the total will be add to $this->result
     */
    public function getTextListAction($page_num = 1,
        $text_type = -1, $author_id = -1, $author_name = "",
        $title = "", $text = "", $create_date = "") {

        //handle null input
        $author_name = $this->handleNullInput($author_name);
        $title = $this->handleNullInput($title);
        $text = $this->handleNullInput($text);
        $create_date = $this->handleNullInput($create_date);

        //check sql injection, and handle illegal input
        $this->sql_handle->checkString($author_name);
        $this->sql_handle->checkString($title);
        $this->sql_handle->checkString($text);
        $this->sql_handle->checkString($create_date);

        $this->sql_handle->checkInt($page_num);
        $this->sql_handle->checkInt($text_type);
        $this->sql_handle->checkInt($author_id);

        $page_num = (int)$page_num;
        $text_type = (int)$text_type;
        $author_id = (int)$author_id;

        //begin to create query
        $limits = array(
            "number" => $this->list_per_page,
            "offset" => ($page_num - 1) * $this->list_per_page
        );

        $require = "author_name LIKE :author_name:
            AND title LIKE :title: AND text LIKE :text:
            AND visible = :visible: AND create_date LIKE :create_date:";

        $parameters = array(
            "author_name" => '%'.$author_name.'%',
            "title" => '%'.$title.'%',
            "text"  => '%'.$text.'%',
            "visible" => 1,
            "create_date"  => '%'.$create_date.'%'
        );

        $types = array(
            "author_name" => Column::BIND_PARAM_STR,
            "title" => Column::BIND_PARAM_STR,
            "text"  => Column::BIND_PARAM_STR,
            "visible" => Column::BIND_PARAM_INT,
            "create_date"  => Column::BIND_PARAM_STR
        );

        //handle author_id and text_type
        if($author_id != -1) {
            $parameters["author_id"] = $author_id;
            $types["author_id"] = Column::BIND_PARAM_INT;
            $require = $require." AND author_id = :author_id:";
        }

        if($text_type != -1) {
            $parameters["text_type"] = $text_type;
            $types["text_type"] = Column::BIND_PARAM_INT;
            $require = $require." AND text_type = :text_type:";
        }

        $textLists = TextLists::find(array(
            $require,
            "bind"      =>  $parameters,
            "bindTypes" =>  $types,
            "limit"     =>  $limits,
            "order"     =>  "status DESC, update_date"
        ));

        $list = array();

        foreach($textLists as $text) {
            array_push($list, $text->convertToArray());
        }

        //add field total
        $this->result['total'] = (int)TextLists::count(array(
            $require,
            "bind"      =>  $parameters,
            "bindTypes" =>  $types
        ));

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }


    /*
     * @param [keyword]
     * @print json(result)
     */
    public function getSelfTextListAction($keyword = "") {
        //check sql injection
        $this->sql_handle->checkString($keyword);

        $list = $this->getSelfTextList($keyword);

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    private function getSelfTextList($keyword) {
        $user = $this->session->get("lb-user");
        $user_id = $user->getId();

        $require = "author_id = :author_id: AND
            (text LIKE :text: OR title LIKE :title:)";

        $parameters = array(
            "author_id" => $user_id,
            "title" => '%'.$keyword.'%',
            "text"  => '%'.$keyword.'%'
        );

        $types = array(
            "author_id" => Column::BIND_PARAM_INT,
            "title" => Column::BIND_PARAM_STR,
            "text"  => Column::BIND_PARAM_STR
        );

        $textList = TextLists::find(array(
            $require,
            "bind"      =>  $parameters,
            "bindTypes" =>  $types,
            "order"     =>  "update_date"
        ));

        $list = array();

        foreach($textList as $text) {
            array_push($list, $text->convertToArray());
        }

        return $list;
    }

    /*
     * @param
     * @print json()
     */
    public function getSelfCommentListAction() {

        $list = $this->getSelfCommentList();

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    private function getSelfCommentList() {

        $user = $this->session->get("lb-user");
        $user_id = $user->getId();

        $textList = Texts::find("author = $user_id");

        $list = array();

        foreach($textList as $text) {
            foreach($text->comments as $comment) {
                array_push($list, $comment->convertToArray());
            }
        }

        return $list;

    }

    private function getTextCommentList($text_id) {

        $text_id = (int)$text_id;

        $commentList = Texts::find("text = $text_id");

        $list = array();

        foreach($commentList as $comment) {
            array_push($list, $comment->convertToArray());
        }

        return $list;

    }

    /*
     * @param comment_id
     * @print json(result)
     */
    public function delTextCommentAction($comment_id) {

        //check sql injection
        $this->sql_handle->checkInt($comment_id);

        $user = $this->session->get("lb-user");
        $user_id = $user->getId();

        $comment_id = (int)$comment_id;
        $comment = Comments::findFirst($comment_id);
        $text_id = $comment->texts->getId();

        if($comment) {
            if($comment->getFrom() == $user_id) {
                $comment->delete();
                $list = $this->getTextCommentList($text_id);
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else if($comment->texts->getAuthor() == $user_id) {
                $comment->delete();
                $list = $this->getTextCommentList($text_id);
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_SUCCESS);
            }
        }else {
            $this->echoResult($this->NO_COMMENT);
        }

    }

    /*
     * @param comment_id
     * @print json(result)
     */
    public function delSelfCommentAction($comment_id) {

        //check sql injection
        $this->sql_handle->checkInt($comment_id);

        $user = $this->session->get("lb-user");
        $user_id = $user->getId();

        $comment_id = (int)$comment_id;
        $comment = Comments::findFirst($comment_id);
        $text_id = $comment->texts->getId();

        if($comment) {
            if($comment->texts->getAuthor() == $user_id) {
                $comment->delete();
                $list = $this->getSelfCommentList($text_id);
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_SUCCESS);
            }
        }else {
            $this->echoResult($this->NO_COMMENT);
        }

    }

    /*
     * @param text_id
     * @print json(result)
     */
    public function getTextAndCommentByTextIdAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $text_id = (int)$text_id;
        if($this->session->has("lb-user")) {
            $user_id = $this->session->get("lb-user")->getId();
        }else {
            $user_id = 0;   //匿名user
        }
        if(is_int($text_id)) {
            $text = Texts::findFirst($text_id); //findFirst by id
            if($text) {
                if($text->getAuthor() == $user_id) {
                    $this->echoResult($this->ACTION_SUCCESS, $text->convertToArray());
                }else {
                    $this->echoResult($this->ACTION_SUCCESS,
                        $text->convertToArrayWithUserId($user_id));
                }
            }else {
                $this->echoResult($this->NO_DATA);
            }
        }else {
            $this->echoResult($this->DATA_ILLEGEAL);
        }
    }

    /*
     * @param blog_id, $the_word
     * @print json()
     */
    public function postWordsAction($blog_id, $the_word) {
        //check sql injection
        $this->sql_handle->checkInt($blog_id);
        $this->sql_handle->checkString($the_word);

        $blog_id = (int)$blog_id;
        if(is_int($blog_id)) {
            $word = new Words();
            $word->setBlog($blog_id);
            $word->setWord($the_word);
            $word->setVisible(1);
            $word->setCreateDate($this->the_date);
            $word->setUpdateDate($this->the_date);
            if($this->session->has("lb-user")) {
                $word->setFrom($this->session->get("lb-user")->getId());
            }else {
                $word->setFrom(0);  //0 for anybody
            }
            if($word->save()) {
                $words = Words::find("blog = $blog_id");

                $list = array();

                foreach($words as $word) {
                    array_push($list, $word->convertToArray());
                }

                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->DATA_ILLEGEAL);
        }
    }

    /*
     * @param blog_id，page_num
     * @print json()
     */
    public function getWordsByBlogIdAction($blog_id, $page_num = 1) {
        //check sql injection
        $this->sql_handle->checkInt($blog_id);
        $this->sql_handle->checkInt($page_num);

        $blog_id = (int)$blog_id;
        $page_num = (int)$page_num;
        if(is_int($blog_id) && is_int($page_num)) {

            $require = "visible = :visible: AND blog = :blog_id:";

            $limits = array(
                "number" => $this->list_per_page,
                "offset" => ($page_num - 1) * $this->list_per_page
            );

            $parameters = array(
                "blog_id" => $blog_id,
                "visible" => 1
            );

            $types = array(
                "blog_id" => Column::BIND_PARAM_INT,
                "visible" => Column::BIND_PARAM_INT
            );

            $wordLists = Words::find(array(
                $require,
                "bind"      =>  $parameters,
                "bindTypes" =>  $types,
                "limit"     =>  $limits,
                "order"     =>  "update_date"
            ));
            $list = array();

            foreach($wordLists as $text) {
                array_push($list, $text->convertToArray());
            }

            //add field total
            $this->result['total'] = (int)Words::count(array(
                $require,
                "bind"      =>  $parameters,
                "bindTypes" =>  $types
            ));

            $this->echoResult($this->ACTION_SUCCESS, $list, true);
        }else {
            $this->echoResult($this->DATA_ILLEGEAL);
        }
    }

    /*
     * @param text_id, comment
     * @print json()
     * TODO:check $comment xss
     */
    public function postCommentAction($text_id, $toUser = -1, $the_comment) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);
        $this->sql_handle->checkInt($toUser);
        $this->sql_handle->checkString($the_comment);

        $text_id = (int)$text_id;
        if(is_int($text_id)) {
            $text = Texts::findFirst($text_id);
            if($text) {
                $comment = new Comments();
                $comment->setText($text->getId());
                $comment->setVisible(0);
                $comment->setFrom($this->session->get("lb-user")->getId());
                $comment->setComment($the_comment);
                if($toUser == -1) {
                    $comment->setTo($text->users->getId());
                    $comment->setOrigin(1);
                }else {
                    $comment->setTo($toUser);
                    $comment->setOrigin(0);
                }

                $create_date = $this->the_date;
                $update_date = $this->the_date;
                $comment->setCreateDate($create_date);
                $comment->setUpdateDate($update_date);

                if($comment->save()) {
                    //get comment list
                    $comments = Comments::find("text = $text_id");

                    $list = array();

                    foreach($comments as $comment) {
                        array_push($list, $comment->convertToArray());
                    }

                    $this->echoResult($this->ACTION_SUCCESS, $list, true);
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }else {
                $this->echoResult($this->NO_TEXT);
            }
        }
    }

    /*
     * @param blog_type
     * @print json()
     */
    public function changeBlogTypeAction($blog_type) {
        //check sql injection
        $this->sql_handle->checkInt($blog_type);

        $blog_type = (int)$blog_type;
        if(is_int($blog_type)) {
            $user = $this->session->get("lb-user");
            $blog = $user->blogs;

            $blog->setBlogType($blog_type);
            if($blog->save()) {
                $this->echoResult($this->ACTION_SUCCESS, $user->convertToArray());
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->DATA_ILLEGEAL);
        }
    }

    /*
     * @param nothing
     * @print json($result)
     */
    public function getBlogTypeListAction() {
        $blogTypeLists = BlogTypes::find();

        $list = array();

        foreach($blogTypeLists as $type) {
            array_push($list, $type->convertToArray());
        }

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    /*
     * @param nothing
     * @print json($result)
     */
    public function getTextTypeListAction() {
        $textTypeLists = TextTypes::find();

        $list = array();

        foreach($textTypeLists as $type) {
            array_push($list, $type->convertToArray());
        }

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    /*
     * @param nothing
     * @print json($result)
     */
    public function getLinkTypeListAction() {
        $linkTypeLists = LinkTypes::find();

        $list = array();

        foreach($linkTypeLists as $type) {
            array_push($list, $type->convertToArray());
        }

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    /*
     * @param blog_id
     * @print json($result)
     */
    public function getLinkListAction($blog_id) {
        //check sql injection
        $this->sql_handle->checkInt($blog_id);

        $blog_id = (int)$blog_id;
        $links = Links::find("blog = $blog_id AND visible = 1");

        $list = array();

        foreach($links as $link) {
            array_push($list, $link->convertToArray());
        }

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    /*
     * @param nothing
     * @print json($result)
     */
    public function getSelfLinkListAction() {

        $list = $this->getSelfLink();

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    private function getSelfLink() {
        $user = $this->session->get("lb-user");
        $blog_id = (int)$user->blogs->getId();
        $links = Links::find("blog = $blog_id");

        $list = array();

        foreach($links as $link) {
            array_push($list, $link->convertToArray());
        }

        return $list;
    }

    /*
     * @param text_id
     * @print json()
     */
    public function delTextByIdAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $text_id = (int)$text_id;
        if(is_int($text_id)) {

            $require = "id = :id: AND author = :author:";
            $user_id = (int)$this->session->get("lb-user")->getId();

            $parameters = array(
                "id" => (int)$text_id,
                "author" => $user_id
            );

            $types = array(
                "id" => Column::BIND_PARAM_INT,
                "author" => Column::BIND_PARAM_INT
            );

            $text = Texts::findFirst(array(
                $require,
                "bind"      =>  $parameters,
                "bindTypes" =>  $types
            ));

            if($text) {
                $comments = $text->comments;

                foreach($comments as $comment) {
                    $comment->delete();
                }

                if($text->delete() == false) {

                    $this->echoResult($this->ACTION_FAILED);
                }else {
                    $texts = Texts::find("author = $user_id");
                    $list  = array();

                    foreach($texts as $text) {
                        array_push($list, $text->convertToArray());
                    }

                    $this->echoResult($this->ACTION_SUCCESS, $list, true);
                }
            }else {
                $this->echoResult($this->NO_TEXT);
            }
        }else {
            $this->echoResult($this->DATA_ILLEGEAL);
        }
    }

    /*
     * @param $text_id, require post data
     * @print json()
    */
    public function updateTextAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        if ($this->session->has("lb-user")) {
            $user = $this->session->get("lb-user");

            $request = $this->request;
            if ($request->isPost() == true) {

                //TODO:check data
                $title = $request->getPost("title");
                $text_type = $request->getPost("text_type");
                $textData = $request->getPost("text");
                $update_date = $this->the_date;

                //check sql injection
                $this->sql_handle->checkString($title);
                $this->sql_handle->checkInt($text_type);
                $this->sql_handle->checkString($textData);

                $require = "id = :id: AND author = :author:";

                $parameters = array(
                    "id" => (int)$text_id,
                    "author" => (int)$this->session->get("lb-user")->getId()
                );

                $types = array(
                    "id" => Column::BIND_PARAM_INT,
                    "author" => Column::BIND_PARAM_INT
                );

                $text = Texts::findFirst(array(
                    $require,
                    "bind"      =>  $parameters,
                    "bindTypes" =>  $types
                ));

                if($text) {
                    $text->setAuthor($user->getId());
                    $text->setTitle($title);
                    $text->setTextType($text_type);
                    $text->setText($textData);
                    $text->setUpdateDate($update_date);

                    if($text->save() == false) {
                        $this->echoResult($this->ACTION_FAILED);
                    }else {
                        $this->echoResult($this->ACTION_SUCCESS, $text->convertToArray());
                    }
                }else {
                    $this->echoResult($this->NO_TEXT);
                }

            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->PLEASE_SIGNIN);
        }
    }

    /*
     * @param no, post request
     * @print json()
    */
    public function addNewLinkAction() {
        $user = $this->session->get("lb-user");
        $blog = $user->blogs;
        $create_date = $this->the_date;
        $update_date = $this->the_date;

        $request = $this->request;
        if ($request->isPost() == true) {
            $url = $request->getPost("url");
            $title = $request->getPost("title");
            $hint = $request->getPost("hint");
            $type = $request->getPost("type");

            //check sql injection
            $this->sql_handle->checkString($url);
            $this->sql_handle->checkString($title);
            $this->sql_handle->checkString($hint);
            $this->sql_handle->checkInt($type);

            //check url form
            if(!$this->checkURL($url)) {
                $this->echoResult($this->URL_WRONG);
                return;
            }

            $link = new Links();
            $link->setUrl($url);
            $link->setBlog($blog->getId());
            $link->setTitle($title);
            $link->setHint($hint);
            $link->setType($type);
            $link->setVisible(1);   //not null
            $link->setCreateDate($create_date);
            $link->setUpdateDate($update_date);

            if($link->save()) {
                $list = $this->getSelfLink();
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->ACTION_FAILED);
        }
    }

    /*
     * @param link_id, post request
     * @print json()
    */
    public function updateLinkAction($link_id) {
        //check sql injection
        $this->sql_handle->checkInt($link_id);

        $link_id = (int)$link_id;

        $user = $this->session->get("lb-user");
        $blog = $user->blogs;
        $update_date = $this->the_date;

        $request = $this->request;
        if ($request->isPost() == true) {
            $url = $request->getPost("url");
            $title = $request->getPost("title");
            $hint = $request->getPost("hint");
            $type = $request->getPost("type");

            //check sql injection
            $this->sql_handle->checkString($url);
            $this->sql_handle->checkString($title);
            $this->sql_handle->checkString($hint);
            $this->sql_handle->checkInt($type);

            //check url form
            if(!$this->checkURL($url)) {
                $this->echoResult($this->URL_WRONG);
                return;
            }

            //find link create by user
            $require = "id = :id: AND blog = :blog:";

            $parameters = array(
                "id" => (int)$link_id,
                "blog" => (int)$blog->getId()
            );

            $types = array(
                "id" => Column::BIND_PARAM_INT,
                "blog" => Column::BIND_PARAM_INT
            );

            $link = Links::findFirst(array(
                $require,
                "bind"      =>  $parameters,
                "bindTypes" =>  $types
            ));

            if($link) {
                $link->setUrl($url);
                $link->setTitle($title);
                $link->setHint($hint);
                $link->setType($type);
                $link->setUpdateDate($update_date);

                if($link->save()) {
                    $list = $this->getSelfLink();
                    $this->echoResult($this->ACTION_SUCCESS, $list, true);
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }else {
                $this->echoResult($this->NO_LINK);
            }
        }else {
            $this->echoResult($this->ACTION_FAILED);
        }
    }

    /*
     * @param link_id
     * @print json()
    */
    public function delLinkAction($link_id) {
        //check sql injection
        $this->sql_handle->checkInt($link_id);

        $link_id = (int)$link_id;

        $user = $this->session->get("lb-user");
        $blog = $user->blogs;

        $require = "id = :id: AND blog = :blog:";

        $parameters = array(
            "id" => (int)$link_id,
            "blog" => (int)$blog->getId()
        );

        $types = array(
            "id" => Column::BIND_PARAM_INT,
            "blog" => Column::BIND_PARAM_INT
        );

        $link = Links::findFirst(array(
            $require,
            "bind"      =>  $parameters,
            "bindTypes" =>  $types
        ));

        if($link) {
            if($link->delete()) {
                $list = $this->getSelfLink();
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->NO_LINK);
        }
    }

    //Administator function

    /*
     * @param nothing
     * @print json($result)
    */
    public function getAllTextAction() {

        $list = $this->getAllText();

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    private function getAllText() {

        $texts = TextLists::find();

        $list =  array();

        foreach($texts as $text) {
            array_push($list, $text->convertToArray());
        }

        return $list;
    }


    /*
     * @param username, password, role
     * @print json()
    */
    public function addUserAction($username, $password, $role) {
        //check sql injection
        $this->sql_handle->checkInt($role);
        $this->sql_handle->checkString($username);

        //check whether had signup
        $require = "username = :username:";

        $parameters = array(
            "username" => $username
        );

        $types = array(
            "username" => Column::BIND_PARAM_STR
        );

        $user = Users::findFirst(array(
            $require,
            "bind"      =>  $parameters,
            "bindTypes" =>  $types
        ));

        if($user) {
            $this->echoResult($this->USERNAME_HAVE_BEEN_USED);
            return;
        }

        if($role == 0) {
            $this->echoResult($this->DATA_ILLEGEAL);
            return;
        }

        $user = new Users();

        $user->setUsername($username);
        $user->setPassword(sha1($password));
        $user->setRole($role);

        if($user->save()) {
            //$this->echoResult($this->ACTION_SUCCESS);
            $blog = new Blogs();
            $blog->setUser($user->getId());
            $blog->setBlogType(1);  //default blogType = 1
            $blog->setCreateDate($this->the_date);
            $blog->setLoginDate($this->the_date);

            if($blog->save() == false) {
                $user->delete();
                $this->echoResult($this->ACTION_FAILED);
            }else {
                $list = $this->getUserList();
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }
        }else {
            $this->echoResult($this->ACTION_FAILED);
        }
    }

    /*
     * @param user_id
     * @print json()
    */
    public function delUserAction($user_id) {
        //check sql injection
        $this->sql_handle->checkInt($user_id);

        $user = Users::findFirst($user_id);

        if($user) {
            if($user->getRole() == 0) {
                $this->echoResult($this->DATA_ILLEGEAL);
                return;
            }

            $blog = $user->blogs;

            if($blog) {
                $blog_id = $blog->getId();
                $user_id = $user->getId();
                $wordList = Words::find("blog = $blog_id");
                $imageList = Images::find("blog = $blog_id");
                $linkList = Links::find("blog = $blog_id");
                $textList = Texts::find("author = $user_id");
                $commentList = Comments::find("from = $user_id OR to = $user_id");

                foreach($wordList as $word) {
                    $word->delete();
                }

                foreach($imageList as $image) {
                    $image->delete();
                }

                foreach($linkList as $link) {
                    $link->delete();
                }

                foreach($commentList as $comment) {
                    $comment->delete();
                }

                foreach($textList as $text) {
                    $text_id = $text->getId();
                    $theCommentList = Comments::find("text = $text_id");

                    foreach($theCommentList as $comment) {
                        $comment->delete();
                    }

                    $text->delete();
                }

                if($blog->delete()) {
                    if($user->delete()) {
                        $list = $this->getUserList();
                        $this->echoResult($this->ACTION_SUCCESS, $list, true);
                    }else {
                        $this->echoResult($this->ACTION_FAILED);
                    }
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }
        }else {
            $this->echoResult($this->NO_USER);
        }
    }

    /*
     * @param user_id, role
     * @print json()
    */
    public function updateUserRoleAction($user_id, $role) {
        //check sql injection
        $this->sql_handle->checkInt($user_id);
        $this->sql_handle->checkInt($role);

        $role = (int)$role;
        $user_id = (int)$user_id;

        if($role != 0) {

            $user = Users::findFirst($user_id);

            if($user) {
                //TODO:check input
                $user->setRole($role);

                if($user->save()) {
                    $list = $this->getUserList();
                    $this->echoResult($this->ACTION_SUCCESS, $list, true);
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }else {
                $this->echoResult($this->NO_USER);
            }

        }else {
            $this->echoResult($this->DATA_ILLEGEAL);
        }
    }

    /*
     * @param user_id, password
     * @print json()
    */
    public function updateUserPasswordAction($user_id, $password) {
        //check sql injection
        $this->sql_handle->checkInt($user_id);

        $user_id = (int)$user_id;

        if(is_int($user_id)) {

            $user = Users::findFirst($user_id);

            if($user) {
                //TODO:check input
                $user->setPassword($password);

                if($user->save()) {
                    $this->echoResult($this->ACTION_SUCCESS);
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }else {
                $this->echoResult($this->NO_USER);
            }

        }else {
            $this->echoResult($this->DATA_ILLEGEAL);
        }
    }

    /*
     * @param text_id
     * @print json()
    */
    public function textRecommendAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $user_id = $this->session->get("lb-user")->getId();
        $text_id = (int)$text_id;

        $text = Texts::findFirst("id = $text_id AND author = $user_id");

        if($text) {
            $text->setRecommend(1);    //1 for recommand

            if($text->save()) {
                $list = $this->getSelfTextList("");
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->NO_TEXT);
        }
    }

    /*
     * @param text_id
     * @print json()
    */
    public function textUndoRecommendAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $user_id = $this->session->get("lb-user")->getId();
        $text_id = (int)$text_id;

        $text = Texts::findFirst("id = $text_id AND author = $user_id");

        if($text) {
            $text->setRecommend(0);    //0 for not recommand

            if($text->save()) {
                $list = $this->getSelfTextList("");
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->NO_TEXT);
        }
    }

    /*
     * @param text_id
     * @print json()
    */
    public function textSetTopAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $user_id = $this->session->get("lb-user")->getId();
        $text_id = (int)$text_id;

        $text = Texts::findFirst("id = $text_id");

        if($text) {
            $text->setStatus(1);    //1 for set top

            if($text->save()) {
                $list = $this->getAllText();
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->NO_TEXT);
        }
    }

    /*
     * @param text_id
     * @print json()
    */
    public function textUndoTopAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $user_id = $this->session->get("lb-user")->getId();
        $text_id = (int)$text_id;

        $text = Texts::findFirst("id = $text_id");

        if($text) {
            $text->setStatus(0);    //0 for not top

            if($text->save()) {
                $list = $this->getAllText();
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->NO_TEXT);
        }
    }

    /*
     * @param text_id
     * @print json()
    */
    public function textSetVisibleAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $user_id = $this->session->get("lb-user")->getId();
        $text_id = (int)$text_id;

        $text = Texts::findFirst("id = $text_id");

        if($text) {
            $text->setVisible(1);

            if($text->save()) {
                $list = $this->getAllText();
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->NO_TEXT);
        }
    }

    /*
     * @param text_id
     * @print json()
    */
    public function textSetInvisibleAction($text_id) {
        //check sql injection
        $this->sql_handle->checkInt($text_id);

        $user_id = $this->session->get("lb-user")->getId();
        $text_id = (int)$text_id;

        $text = Texts::findFirst("id = $text_id");

        if($text) {
            $text->setVisible(0);

            if($text->save()) {
                $list = $this->getAllText();
                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->ACTION_FAILED);
            }
        }else {
            $this->echoResult($this->NO_TEXT);
        }
    }

    /*
     * @param $comment_id
     * @print json()
    */
    public function commentSetVisibleAction($comment_id) {
        //check sql injection
        $this->sql_handle->checkInt($comment_id);

        $user_id = $this->session->get("lb-user")->getId();

        $comment_id = (int)$comment_id;

        $comment = Comments::findFirst($comment_id);

        if($comment) {
            $the_user_id = $comment->texts->getAuthor();
            if($user_id == $the_user_id) {
                $comment->setVisible(1);

                if($comment->save()) {

                    $list = $this->getSelfCommentList();

                    $this->echoResult($this->ACTION_SUCCESS, $list, true);
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }else {
                $this->echoResult($this->DATA_ILLEGEAL);
            }
        }else {
            $this->echoResult($this->NO_COMMENT);
        }
    }

    /*
     * @param $comment_id
     * @print json()
    */
    public function commentSetInvisibleAction($comment_id) {
        //check sql injection
        $this->sql_handle->checkInt($comment_id);

        $user_id = $this->session->get("lb-user")->getId();

        $comment_id = (int)$comment_id;

        $comment = Comments::findFirst($comment_id);

        if($comment) {
            $the_user_id = $comment->texts->getAuthor();
            if($user_id == $the_user_id) {
                $comment->setVisible(0);

                if($comment->save()) {

                    $list = $this->getSelfCommentList();

                    $this->echoResult($this->ACTION_SUCCESS, $list, true);
                }else {
                    $this->echoResult($this->ACTION_FAILED);
                }
            }else {
                $this->echoResult($this->DATA_ILLEGEAL);
            }
        }else {
            $this->echoResult($this->NO_COMMENT);
        }
    }

    /*
     * @param nothing
     * @print json()
     */
    public function getUserListAction() {

        $list = $this->getUserList();

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    private function getUserList() {
        $userList = Users::find("role > 0");

        $list = array();

        foreach($userList as $user) {
            array_push($list, $user->convertToArray());
        }

        return $list;
    }

    /*
     * @param nothing
     * @print json()
     */
    public function getSelfWordListAction() {

        $user = $this->session->get("lb-user");
        $blog = $user->blogs;

        $blog_id = $blog->getId();
        $words = Words::find("blog = $blog_id");

        $list = array();

        foreach($words as $word) {
            array_push($list, $word->convertToArray());
        }

        $this->echoResult($this->ACTION_SUCCESS, $list, true);
    }

    /*
     * @param nothing
     * @print json()
     */
    public function delWordByIdAction($word_id) {
        //check sql injection
        $this->sql_handle->checkInt($word_id);

        $user = $this->session->get("lb-user");
        $user_id =  $user->getId();
        $blog = $user->blogs;

        $blog_id = $blog->getId();
        $word_id = (int) $word_id;
        $word = Words::findFirst($word_id);

        if($word) {
            if($word->getBlog() == $blog_id or $word->getFrom() == $user_id) {
                $word->delete();
                $words = Words::find("blog = $blog_id");

                $list = array();
                foreach($words as $word) {
                    array_push($list, $word->convertToArray());
                }

                $this->echoResult($this->ACTION_SUCCESS, $list, true);
            }else {
                $this->echoResult($this->NO_WORD);
            }
        }else {
            $this->echoResult($this->NO_WORD);
        }
    }
}
